home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / Files / PBCatSearch / PBCatSearch sample.c next >
Encoding:
C/C++ Source or Header  |  1995-02-08  |  13.3 KB  |  341 lines  |  [TEXT/MPS ]

  1. /* This small sample shows how to use the PBCatSearch function.  */
  2. /* It presents a dialog where you can enter any Creator and File Type, then it */
  3. /* searches for one (1) file with that creator and type */
  4. /* When it finds it, it will show you the file name. */
  5. /* C.K. Haun */
  6. /* Apple Developer Tech Support */
  7. /* Comments or request, ALink C.K.HAUN */
  8. /* Oct 16, 1991, Tokyo */
  9.  
  10. #include <Dialogs.h>
  11. #include <Controls.h>
  12. #include <QuickDraw.h>
  13. #include <Windows.h>
  14. #include <ToolUtils.h>
  15. #include <OSUtils.h>
  16. #include <Menus.h>
  17. #include <Fonts.h>
  18. #include <resources.h>
  19. #include <memory.H>
  20. #include <files.h>
  21.  
  22. /* constants for this application */
  23. /* two dialog boxes */
  24. #define kSearch 128
  25. #define kFoundIt 129
  26. /* one alert box */
  27. #define kAsk 130
  28.  
  29. #define kOneKilobyte 1024
  30.  
  31. /* constants for key codes I will be using for the dialog filter */
  32. enum  {
  33.     kEnterKey = 0x03, kBackSpace = 8, kReturnKey = 0x0D, kTabKey, kEscKey = 0x1B, kLeftArrow, kRightArrow, kUpArrow, kDownArrow,
  34.         kDeleteKey = 0x7F
  35. };
  36. /* prototypes for this file */
  37.  
  38. void DoCatSearch(void);
  39. ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem);
  40. pascal Boolean letterFilter(DialogPtr dialer, EventRecord *myDialogEvent, short *theDialogItem);
  41. Boolean IsEditKey(char theKey);
  42.  
  43. #ifdef powerc
  44.    QDGlobals    qd;
  45. #endif
  46.  
  47.  
  48. /* the main routine.  All this does is initialize managers and call DoCatSearch */
  49. main()
  50. {
  51.     
  52.     InitGraf(&qd.thePort);
  53.     InitFonts();
  54.     InitWindows();
  55.     InitMenus();
  56.     TEInit();
  57.     InitDialogs(nil);
  58.     InitCursor();
  59.     DoCatSearch();
  60. }
  61.  
  62. /* DoCatSearch asks the user for the Creator and File type of the file to be found. */
  63. /* Then, it initializes the parameter blocks for the PBCatSearch call, and makes */
  64. /* the call.  When it finds a file with the correct creator and file type, it */
  65. /* shows the user */
  66. void DoCatSearch(void)
  67. {
  68.     short bufferSize = kOneKilobyte * 16; /* I will be using this to make  */
  69.                                             /* the optimization buffer */
  70.     OSErr myError;    /* general error variable */
  71.     DialogPtr search; /* dialog pointer varialbe */
  72.     ModalFilterUPP myModalFilterUPP;
  73.     short          alertResult;
  74.  
  75.     /* here I am initializing the cat search parameter block (csBlockPtr) using */
  76.     /* NewPointerClear so I know that all the fields in the parameter block */
  77.     /* will be clear before I start.  This helps prevent errors */
  78.     CSParamPtr csBlockPtr = NewPtrClear(sizeof(CSParam));
  79.     
  80.     short hitItem = 0; /* for the dialog routines */
  81.     long dirIDUnused;    /* for GetVol use */
  82.     /* these are the default Creator and Type I will be looking for.  These can */
  83.     /* be changed by the user when the dialog box is presented to them */
  84.     Str32 Creator = "\pMACS";
  85.     Str32 Type = "\pFNDR";
  86.  
  87.     Str32 nulString = "\p"; /* an empty string to pass to PBCatSearch */
  88.     
  89.     /* Open a Dialog and ask the user for the Creator and Type they wish to */
  90.     /* search for */
  91.     search = GetNewDialog(kAsk, nil, (WindowPtr)-1);
  92.             
  93.     /* create a modal filter UPP- this will be freed when the */
  94.     /* application quits */
  95.     
  96.     myModalFilterUPP = NewModalFilterProc(letterFilter);
  97.     while (hitItem != ok) { /* wait until they hit the 'ok' button */
  98.         ModalDialog(myModalFilterUPP, &hitItem);
  99.     }
  100.     /* now get the creator and file type they entered. */
  101.     GetDialogItemText((Handle)SnatchHandle(search, 4), Creator);
  102.     GetDialogItemText((Handle)SnatchHandle(search, 5), Type);
  103.     
  104.     DisposeDialog(search); /* remove the dialog from the screen */
  105.         
  106.     /* initialize the parameter block */
  107.     /* first I see if we got the memory we need */
  108.     if (csBlockPtr) {
  109.         /* yes, we have the memory to work.  Build the parameter block */
  110.         
  111.         /* First get the memory for the two other parameter blocks we need */
  112.         /* these blocks are used to give PBCatSearch to exact information */
  113.         /* it needs to match a file */
  114.         csBlockPtr->ioSearchInfo1 = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
  115.         csBlockPtr->ioSearchInfo2 = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
  116.         /*  check to be sure we got the memory we need */
  117.         if (csBlockPtr->ioSearchInfo1 && csBlockPtr->ioSearchInfo2) {
  118.             /* we have memory */
  119.             /* Now allocate a buffer to hold the result of the PBCatSearch call */
  120.             /* this is an array of ioMatchPtr, which is defined as an FSSpecPtr */
  121.             /* so we will get the size of an FSSpec record  */
  122.             /* I am only asking for one file, so I will only ask for that much memory */
  123.             csBlockPtr->ioMatchPtr = (FSSpecPtr)NewPtrClear(sizeof(FSSpec) * 1);        /* only looking for 1 */
  124.             if (csBlockPtr->ioMatchPtr) {
  125.             /* got the memory for that */
  126.                 /* Now see if we can create an optimization buffer */
  127.                 /* I will start by asking for a 16K buffer */
  128.                 /* If I cannot get that, I will keep reducing my request  */
  129.                 /* until I get to zero.  A one  K buffer is better than no  */
  130.                 /* buffer at all */
  131.                 while(bufferSize){                
  132.                 csBlockPtr->ioOptBuffer = NewPtr(bufferSize);
  133.                 if(csBlockPtr->ioOptBuffer){
  134.                 break;
  135.                 } else {
  136.                 bufferSize -= kOneKilobyte;
  137.                 }
  138.                 }
  139.                 if (csBlockPtr->ioOptBuffer)
  140.                     csBlockPtr->ioOptBufSize = bufferSize;
  141.                 else
  142.                     csBlockPtr->ioOptBufSize = 0;           /* no buffer, sorry */
  143.                 /* I want to find one file */
  144.                 csBlockPtr->ioReqMatchCount = 1;
  145.                 /* No timeout.  PBCatSearch will keep running until it finds */
  146.                 /* a file or searches the whole volume */
  147.                 csBlockPtr->ioSearchTime = 0;               /* no timeout */
  148.                 /* Change this parameter in a real application.  In a real application, */
  149.                 /* you would want to come back periodically (every 2 seconds or so) */
  150.                 /* to do various things like; */
  151.                 /* 1) Spin a 'wait' cursor */
  152.                 /* 2) Update a thermometer bar */
  153.                 /* 3) Call WaitNextEvent, so the user can switch out */
  154.                 /* of your application while you are searching */
  155.                 /* Watch the Finder's "Find" command work so you can see how this */
  156.                 /* is done */
  157.             }
  158.         }
  159.     }
  160.     /* This sample only works on the default directory, so I am getting the  */
  161.     /* volume reference number for that volume here */
  162.     HGetVol(nil, &csBlockPtr->ioVRefNum, &dirIDUnused);     /* get default volume for search */
  163.     /* make sure these two pointer are clear */
  164.     csBlockPtr->ioSearchInfo1->hFileInfo.ioNamePtr = nil;
  165.     csBlockPtr->ioSearchInfo2->hFileInfo.ioNamePtr = nil;
  166.     
  167.     /* Here I am moving the User's selected creator and file type into the first */
  168.     /* search parameter block.  If they entered a bad creator or type, I default to the  */
  169.     /* Finder */
  170.     if (Creator[0] == 4)
  171.         BlockMove((Ptr)&Creator + 1, (Ptr)&csBlockPtr->ioSearchInfo1->hFileInfo.ioFlFndrInfo.fdCreator, 4);
  172.     else
  173.         csBlockPtr->ioSearchInfo1->hFileInfo.ioFlFndrInfo.fdCreator = 'MACS';
  174.     
  175.     if (Type[0] == 4)
  176.         BlockMove((Ptr)&Type + 1, (Ptr)&csBlockPtr->ioSearchInfo1->hFileInfo.ioFlFndrInfo.fdType, 4);
  177.     else
  178.         csBlockPtr->ioSearchInfo1->hFileInfo.ioFlFndrInfo.fdType = 'FNDR';
  179.     /* This is the paramter that specifies HOW to search */
  180.     csBlockPtr->ioSearchBits = fsSBFlFndrInfo;
  181.     /* in this case, I am saying to search by Finder information. */
  182.     /* there are MANY values allowed here, and you can also use */
  183.     /* many combinations, as*/
  184.     /*     fsSBPartialName    search for partial names
  185.     fsSBFullName    search for full names
  186.     fsSBFlAttrib    ""    directory flags
  187.     fsSBFlFndrInfo    Finder info
  188.     fsSBFlLgLen        data fork logical size
  189.     fsSBFlPyLen        dat fork physical size
  190.     fsSBFlRLgLen    resource fork logical size
  191.     fsSBFlRPyLen    resource fork physical size
  192.     fsSBFlCrDat        creation date
  193.     fsSBFlMdDat        modification date
  194.     fsSBFlBkDat        backup date
  195.     fsSBFlXFndrInfo    more finder info
  196.     fsSBFlParID        file parent ID (directory ID)
  197.     fsSBDrUsrWds    directory information
  198.     fsSBDrNmFls        number of files in a folder
  199.     fsSBDrCrDat        folder creation date
  200.     fsSBDrMdDat        ""       mod date
  201.     fsSBDrBkDat        ""        backup date
  202.     fsSBDrFndrInfo    finder folder information
  203.  */
  204.     /* and you can combine many of these, to create unique searches */
  205.     
  206.     /* Set up the second search parameter block */
  207.     /* For the search I am doing (creator/filetype) these need to be set to -1 */
  208.     csBlockPtr->ioSearchInfo2->hFileInfo.ioFlFndrInfo.fdCreator = 0xFFFFFFFF;
  209.     csBlockPtr->ioSearchInfo2->hFileInfo.ioFlFndrInfo.fdType = 0xFFFFFFFF;
  210.     /* For other searches (like by modification date) this would indicate the end of the */
  211.     /* search range.  This allows you to, for example, search for all the files  */
  212.     /* modified between October 1 1991 and October 12 1991 */    
  213.     /* Many more combinations are possible, see Inside Mac VI */
  214.     
  215.     /* Setting up my 'wait' dialog */
  216.      ParamText(Creator, Type, "\p", "\p");
  217.       
  218.     /* Show a dialog so the user knows that we are searching for their file */
  219.      search = GetNewDialog(kSearch, nil, (WindowPtr)-1);
  220.         
  221.      DrawDialog(search);
  222.    
  223.      /* Change the cursor to a watch */
  224.      SetCursor(*(GetCursor(4)));
  225.     
  226.      /* Search.  I am searching syncronously in this case */
  227.      myError = PBCatSearch(csBlockPtr, false);
  228.  
  229.     /* returned, get rid of the dialog */
  230.      DisposeDialog(search);
  231.         
  232.      /* change the cursor back to an arrow */
  233.      InitCursor();
  234.  
  235.     /* See if there were any errors.  Also, see if a file was found */
  236.     /* ioActMatchCount will show how many files were really found if  */
  237.     /* we had asked for more than one */
  238.     if (myError == noErr && csBlockPtr->ioActMatchCount != 0) {
  239.         /* found a file with no errors.  Put the filename in a ParamText */
  240.         /* string show we can show the user */
  241.         
  242.         ParamText(&csBlockPtr->ioMatchPtr[0].name, "\p", "\p", "\p");
  243.         /* show the user */
  244.         alertResult = Alert(kFoundIt, nil);
  245.     }
  246.     
  247.     /* no matter what happened, kill the memory we had allocated */
  248.     if (csBlockPtr) {
  249.         if (csBlockPtr->ioSearchInfo1)
  250.             DisposePtr((Ptr)csBlockPtr->ioSearchInfo1);
  251.         if (csBlockPtr->ioSearchInfo2)
  252.             DisposePtr((Ptr)csBlockPtr->ioSearchInfo2);
  253.         if (csBlockPtr->ioMatchPtr)
  254.             DisposePtr((Ptr)csBlockPtr->ioMatchPtr);
  255.         if (csBlockPtr->ioOptBuffer)
  256.             DisposePtr((Ptr)csBlockPtr->ioOptBuffer);
  257.         DisposePtr((Ptr)csBlockPtr);
  258.     }
  259.     
  260.     /* catsearch section end */
  261.     
  262. }
  263.  
  264.  
  265.  
  266. /* The rest of this file is routines to support the creator/type dialog box, they */
  267. /* are not important to PBCatSearch.  All of these routines were taken from my */
  268. /* DialogBits sample code, please see that code for more Dialog Manager techniques */
  269.  
  270. /* Gets the ControlHandle for the item you want in the dialog box thebox.  */
  271. /* Handy for setting checkboxes and radio buttons */
  272. ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem)
  273. {
  274.     short itemtype;
  275.     Rect itemrect;
  276.     Handle thandle;
  277.     
  278.     GetDialogItem(thebox, theGetItem, &itemtype, &thandle, &itemrect);
  279.     return((ControlHandle)thandle);
  280. }
  281.  
  282. /* This is our dialog filter, does not let the user type more than 4 characters */
  283. /* in the edit lines, since Creators and Types are four characters only */
  284. pascal Boolean letterFilter(DialogPtr dialer, EventRecord *myDialogEvent, short *theDialogItem)
  285. {
  286.     Boolean returnVal = false;
  287.     char myStr[10];
  288.     char theKey;
  289.     /* Find out how many characters are currently selected */
  290.     short selStart = (*((DialogPeek)dialer)->textH)->selStart;
  291.     short selEnd = (*((DialogPeek)dialer)->textH)->selEnd;
  292.     /* Was this a Key event? */
  293.     if ((myDialogEvent->what == keyDown) || (myDialogEvent->what == autoKey)) {
  294.         /* yes,check for return key first */
  295.         theKey = myDialogEvent->message & charCodeMask;
  296.         if (theKey == kReturnKey || theKey == kEnterKey) {
  297.         /* if they typed Return or Enter, exit the dialog */
  298.             *theDialogItem = 1; /* say item 1 (OK button) hit */
  299.             return(true);
  300.         }
  301.         /* Here I am getting the text of the currently active edit line */
  302.         GetDialogItemText((Handle)SnatchHandle(dialer, ((DialogPeek)dialer)->editField + 1), myStr);
  303.         /* Will this key make the line hold more than 4 characters? */
  304.         if (myStr[0] > 3) {/* yes, see what the key is */
  305.             /* if the jey is an edit key (like a right arrow), allow the  */
  306.             /* keystroke.  Also allow the keystroke if there are any  */
  307.             /* characters selected, since they will be replaced by this new */
  308.             /* keystroke */
  309.             if (IsEditKey(theKey) || (selStart != selEnd)) {
  310.             /* this is a safe key, let the Dialog Manager add it to the edit line */
  311.                 returnVal = false;                          /* don't filter out editing keys */
  312.             } else {
  313.             /* Not an edit key, and nothing selected.  This would cause the */
  314.             /* text in this edit line to be too long (over 4 characters) */
  315.             /* so don't let it in */
  316.                 SysBeep(1);                                 /* complain a little */
  317.                 returnVal = true;                           /* tell the dialog manager that we handled this already and */
  318.                 /* it doesn't have to, so the keystroke will _not_ get */
  319.                 /* added to the edit line */
  320.                 
  321.             }
  322.         }
  323.     }
  324.     return(returnVal);
  325. }
  326.  
  327. /* IsEditKey is a handy routine to see if the current key is an edit key, like */
  328. /* an arrow key */
  329. Boolean IsEditKey(char theKey)
  330. {
  331.     register qq;
  332.     char editChars[] =  {
  333.         kLeftArrow, kUpArrow, kRightArrow, kDownArrow, kBackSpace, kTabKey
  334.     };
  335.     for (qq = 0; qq < sizeof(editChars); qq++) {
  336.         if (theKey == editChars[qq])
  337.             return(true);
  338.     }
  339.     return(false);
  340. }
  341.